package com.suzhe.ymall.promotion.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.suzhe.ymall.common.enums.MessageStatusEnum;
import com.suzhe.ymall.common.pojo.ApiResEntity;
import com.suzhe.ymall.promotion.enums.CouponStatusEnum;
import com.suzhe.ymall.promotion.enums.CouponTypeEnum;
import com.suzhe.ymall.promotion.mapper.UserCouponMapper;
import com.suzhe.ymall.promotion.param.LockCouponParam;
import com.suzhe.ymall.promotion.pojo.Coupon;
import com.suzhe.ymall.promotion.pojo.UserCoupon;
import com.suzhe.ymall.promotion.service.ICouponService;
import com.suzhe.ymall.promotion.service.IMessageLogService;
import com.suzhe.ymall.promotion.service.IUserCouponService;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户优惠券表 服务实现类
 * </p>
 *
 * @author suzhe
 * @since 2019-08-18
 */
@Service
@Slf4j
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
    @Autowired
    InterProcessMutex userCouponLock;//更新用户优惠券的状态，用到的锁


    @Autowired
    ICouponService iCouponService;

    @Autowired
    IMessageLogService iMessageLogService;

    @Override
    public ApiResEntity lockUserCoupon(LockCouponParam lockCouponParam) {
        boolean lock = false;
        try {
            //分布式锁
            lock = userCouponLock.acquire(5, TimeUnit.SECONDS);
            if (lock){
                UserCoupon userCoupon = getById(lockCouponParam.getUserCouponId());
                if (!CouponStatusEnum.AVAILABLE.value().equals(userCoupon.getStatus())){
                    return ApiResEntity.error("该优惠券不可用");
                }
                userCoupon.setOrderNo(lockCouponParam.getOrderNo());
                userCoupon.setLockTime(new Date());
                userCoupon.setStatus(CouponStatusEnum.LOCKED.value());
                boolean update = updateById(userCoupon);
                if (!update){
                    return ApiResEntity.error("锁定优惠券失败");
                }
                Coupon coupon = iCouponService.getById(userCoupon.getCouponId());
                Integer couponValue = coupon.getCouponValue();
                long actualPay = 0;
                Long totalPay = lockCouponParam.getTotalPay();
                if (CouponTypeEnum.FULL_REDUCTION.value().equals(coupon.getCouponType())){
                    actualPay = totalPay - couponValue;
                }else{
                    long amount = totalPay * ((100 - couponValue) / 100);
                    if (0 == coupon.getDiscountLimit() && amount > coupon.getDiscountLimit()){
                        amount = coupon.getDiscountLimit();
                    }
                    actualPay = totalPay - amount;
                }

                return ApiResEntity.ok(actualPay);
            }
        } catch (Exception e) {
            log.error("lockUserCoupon error",e);
        }finally {
            if(lock){
                try {
                    userCouponLock.release();
                } catch (Exception e) {
                    log.error("lockUserCoupon release",e);
                }
            }
        }
        log.error("lockUserCoupon fail:{}",lockCouponParam);
        return ApiResEntity.error();
    }

    @Async("asyncServiceExecutor") //此处方法实现被加入到线程池中执行。当前的方法立刻返回，上级调用即可结束
    @Override
    public void rollbackOrder(String messageId,String orderNo) {
        UserCoupon userCoupon = getOne(new QueryWrapper<UserCoupon>()//
                .eq("order_no", orderNo));
        if (userCoupon != null && CouponStatusEnum.LOCKED.value().equals(userCoupon.getStatus())){
            userCoupon.setStatus(CouponStatusEnum.AVAILABLE.value());
            updateById(userCoupon);
        }
        iMessageLogService.updateMeesageStatus(messageId, MessageStatusEnum.DONE);

    }

    @Async("asyncServiceExecutor") //此处方法实现被加入到线程池中执行。当前的方法立刻返回，上级调用即可结束
    @Override
    public void orderSuccess(String messageId,String orderNo) {
        UserCoupon userCoupon = getOne(new QueryWrapper<UserCoupon>()//
                .eq("order_no", orderNo));
        if (userCoupon != null && CouponStatusEnum.LOCKED.value().equals(userCoupon.getStatus())){
            userCoupon.setStatus(CouponStatusEnum.USED.value());
            updateById(userCoupon);
        }
        iMessageLogService.updateMeesageStatus(messageId, MessageStatusEnum.DONE);
    }
}
